#include <string>
#include "Peer.h"
#include "Common.h"

void displayHelp(){
    cout<<"Possible commands:"<<endl;
    cout<<"connect - join the network"<<endl;
    cout<<"list - list the files available"<<endl;
    cout<<"tag <filename> [version] - tag the file as a stable version (disabled when not on network)"<<endl;
    cout<<"save <filename> [version] - save the modifications to a file (disabled when not on network)"<<endl;
    cout<<"create <filename with absolute directory> - insert this file to share"<<endl;
    cout<<"disconnect - leave the network"<<endl;
    cout<<"modify <filename> [version] - modify the file"<<endl;
    cout<<"open <filename> [version] - open the file"<<endl;
    cout<<"close <filename> [version] - close the file"<<endl;
    cout<<"delete <filename> - delete the file"<<endl;
    cout<<"exit - exit the program"<<endl;
    cout<<"help - display this again"<<endl;
    return;
}

void displayError(string message, int status){
    printf("ERROR:%s TYPE 0x%x\n", message.c_str(), status);
}

// [**] exit will return error if we exit when disconnected
// [**] 
int main(int argc, char *argv[]) {

    // output possible commands
    cout<<"========================"<<endl;
    cout<<"Welcome to VFS!"<<endl;
    cout<<"July 19st, 2012"<<endl;
    cout<<"By Michael Liu, Xin Zhao"<<endl;
    cout<<"========================"<<endl;
    displayHelp();

    string myIP = "";
    int myPort = PORT;
    string myDeviceType = "";

    if (argc == 4) {
        myIP += argv[1];
        myPort = atoi(argv[2]);
        myDeviceType += argv[3];
    } else {
        cerr << "incorrect format: ./<executable> <ip> <port> <device>" << endl;
        cerr << "devices available: " << endl;
        return -1;
    }

    // [*] need to display how to input device type

    // initialize stuff here.
    Peer *localPeer = new Peer(myIP, myPort, myDeviceType);
    int status = SAFE;

    // commandline interface
    // Available commands: insert, query, join, leave, exit.

    bool EXIT = false;

    while(!EXIT){
        printf(">");
        string line;
        getline(cin, line);

        stringstream sin( line );

        string command;
        sin >> command;
        
        if (command == "connect") {
            DBG_PRINTF(("connect was called\n"));
            status = localPeer->join();
            if (status < 0) displayError("Join failed!\n", status);
        } else if (command == "list") {
            DBG_PRINTF(("list was called\n"));
            localPeer->list();
        } else if (command == "disconnect"){
            status = localPeer->leave();
            if(status == errNotConnected)
            {
                displayError("Not connected to the network. Abort leave.\n", status);
            }
        } else if (command == "exit") {
            localPeer->leave();
            printf("Exiting the Program...\n");
            printf("Goodbye!\n");
            EXIT = true;
        } else if (command == "create") {
            string fileName = "";            
            sin >> fileName;

            status = localPeer->create(fileName);
            if(status == errFileAlreadyExist)
            {
                displayError("File already exist.\n", status);
            }else if(status == errNoFileFound){
                displayError("Cannot find file.\n", status);
            }
        } else if (command == "delete") {
            string fileName = "";            
            sin >> fileName;

            status = localPeer->deleteFile(fileName);
        } else if (command == "modify") {
            string fileName = "";            
            sin >> fileName;
            
            int version = 0;
            sin >> version;

            DBG_PRINTF(("modify: file = %s, version = %i\n", fileName.c_str(), version));

            status = localPeer->modify(fileName, version);
        } else if (command == "open") {
            string fileName = "";            
            sin >> fileName;
            
            int version = 0;
            sin >> version;

            DBG_PRINTF(("open: file = %s, version = %i\n", fileName.c_str(), version));

            status = localPeer->openFile(fileName, version);
        } else if (command == "close") {
            string fileName = "";            
            sin >> fileName;
            
            int version = 0;
            sin >> version;

            DBG_PRINTF(("close: file = %s, version = %i\n", fileName.c_str(), version));

            status = localPeer->closeFile(fileName, version);
        } else if (command == "save") {
            string fileName = "";            
            sin >> fileName;
            
            int version = 0;
            sin >> version;

            DBG_PRINTF(("save: file = %s, version = %i\n", fileName.c_str(), version));

            status = localPeer->save(fileName, version);
        } else if (command == "tag") {
            string fileName = "";            
            sin >> fileName;

           
            int version = 0;
            sin >> version;

            DBG_PRINTF(("tag: file = %s, version = %i\n", fileName.c_str(), version));

            status = localPeer->tag(fileName, version);
        } else if(command == "help"){
            displayHelp();
        } else if(command == "test"){
            localPeer->test();
        } else {
            displayError("This command does not exists. Please type help to display all possible commands.\n", errUnknownWarning);
        }

    }

    // cleanup
    delete localPeer;

    return 0;
}

